/**********************************************************************************
// Input Header File
// 
// Creation:	14 Oct 2007
// Updated:		17 Abr 2011
// Compiler:	Visual Studio 2010
//
// Notes:		Input control class.
//				Manages keyboard, mouse and joystick input
//
**********************************************************************************/

#ifndef _ANABELE_INPUT_H_
#define _ANABELE_INPUT_H_

#pragma warning (disable: 4251) // list needs dll-interface warnings

/**********************************************************************************/

// Defines
#define INITGUID						// make sure directX guids are included
#define DIRECTINPUT_VERSION 0x0800		// use directinput version 8

/**********************************************************************************/

//Includes
#include <dinput.h>
#include <xinput.h>
#include <list>
#include <string>
#include "WindowsGame.h"
using std::list;
using std::string;;

/**********************************************************************************/
// Global Constants and Enumerations

enum MouseButtons {MouseLeftButton, MouseRightButton, MouseMiddleButton};
enum MouseAxis    {MouseAxisX, MouseAxisY, MouseWheel};
enum JoystickAxis {JoyAxisX, JoyAxisY, JoyAxisZ, JoyAxisRX, JoyAxisRY, JoyAxisRZ};
enum Xbox360Ctrl  
{	
	DpadUp, DpadDown, DpadLeft, DpadRight,  // Dpad
	StartButton, BackButton,				// Buttons
	LeftThumb, RightThumb,					// Buttons
	LeftShoulder, RightShoulder,			// Buttons
	Abutton, Bbutton, Xbutton, Ybutton,		// Buttons
	LTtrigger, RTtrigger,					// Trigger range is 0 to 255
	LXthumb, LYthumb, RXthumb, RYthumb		// Tumbstick range is -32768 to 32767
};

/**********************************************************************************/
// Type Definitions

// joysticks Information
typedef struct JoyInfoType
{
	GUID   guid;
	string name;

} JoyInfo;

// joystick control objects
typedef struct JoyObjectsType
{
	GUID   guid;
	DWORD  type;
	string name;

} JoyObjs;

/**********************************************************************************/

class DLL Input
{
private:
	LPDIRECTINPUT8 lpDI;										// pointer to direct input interface

	LPDIRECTINPUTDEVICE8 lpDIkey;								// pointer to keyboard device
	LPDIRECTINPUTDEVICE8 lpDImouse;								// pointer to the mouse device
	LPDIRECTINPUTDEVICE8 lpDIjoy;								// pointer to joystick device

	list<JoyInfo> joysticks;									// joystick device information
	list<JoyObjs> joystickObjects;								// list of input elements for selected joystick

	list<JoyInfo>::const_iterator selectedJoystick;				// points to selected joystick

	UCHAR keystate[256];										// keyboard state data
	bool keyctrl[256];											// keyboard released keys control
	DIMOUSESTATE mousestate;									// mouse state data
	DIJOYSTATE joystate;										// joystick state data
	XINPUT_STATE xbox360state;									// xbox360 controller state data

public:
	Input();													// constructor
	~Input();													// destructor

	bool Initialize();											// initialize direct input
	bool InitializeKeyboard();									// initialize keyboard
	bool InitializeMouse();										// initialize mouse
	bool InitializeJoystick();									// initialize selected joystick
	bool InitializeXbox360(int controller = 0);					// initialize xbox360 controller

	bool GetKeyboardState();									// update the keyboard state structure
	bool GetMouseState();										// update the mouse state structure
	bool GetJoystickState();									// update the joystick state structure
	bool GetXbox360State(int controller = 0);					// update the xbox360 state structure
	
	bool KeyPressed(int key);									// return true if the key is pressed
	bool KeyReleased(int key);									// return true if the key is released
	bool KeyPressRelease(int key);								// register another press only after release
	void KeyReset();											// reset release state of all keys

	bool MouseButton(int button);								// get state of the given mouse button
	long MouseAxis(int axis); 									// get mouse movement on the given axis

	bool JoystickButton(int button);							// get state of the given joystick button
	long JoystickAxis(int axis); 								// get joystick movement on the given axis
	long JoystickPov(int pov);									// get the D-pad movement
	bool JoystickSelectNext();									// select next available joystick
	bool JoystickSelectPrev();									// select previous available joystick
	const char* JoystickName();									// return the name of the selected joystick
	list<JoyObjs>& JoystickObjects();							// return list of joystick objects 

	int  Xbox360Button(int button);								// get state of the given xbox360 button
	int  Xbox360Trigger(int trigger);							// get the trigger movement value
	int  Xbox360ThumbStick(int stick);							// get the stick movement value
	void Xbox360Vibrate(int controller = 0, 
		int left = 65535, int right = 65535);					// vibrate the controller 
};

/**********************************************************************************/

// InLine Member Functions

// return true if the key is pressed
inline bool Input::KeyPressed(int key) 
{ return (keystate[key] && 0x80); }	

// return true if the key is released
inline bool Input::KeyReleased(int key) 
{ return !(keystate[key] && 0x80); }

// reset release state of all keys
inline void Input::KeyReset()
{ ZeroMemory(&keyctrl, sizeof(keyctrl)); }

// return the name of the selected joystick
inline const char* Input::JoystickName() 
{ return (*selectedJoystick).name.c_str(); }

// return list of joystick objects
inline list<JoyObjs>& Input::JoystickObjects() 
{ return joystickObjects;} 

/**********************************************************************************/

// callback function that enumerate joysticks
BOOL CALLBACK JoystickEnumerate(LPCDIDEVICEINSTANCE lpDDi, LPVOID data);

// callback function that enumerate objects of the joystick
BOOL CALLBACK JoystickEnumObjects(LPCDIDEVICEOBJECTINSTANCE lpDIdoi, LPVOID data);

/**********************************************************************************/

#endif